package com.open.web.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.time.Instant;


/**
 * @author: codex
 * @Date: 2024/7/19 下午2:57
 * @Version: V1.0
 * @description: desc: 时间戳校验拦截器
 */

@Slf4j
@Component
public class RequestInterceptor implements HandlerInterceptor {

    @Value("${request.timestamp.enabled:false}")
    private boolean enabled = true;

    private byte timeout = (byte) 1 & 0xFF;

    private byte position = (byte) 11 & 0xFF;

    private byte length = (byte) 13;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!enabled) {
            return true;
        }
        var t = request.getParameter("t");
        if (!StringUtils.hasText(t)) {
            return false;
        }
        if (log.isDebugEnabled()) {
            log.debug("t:{}", t);
        }
        Instant requestTimes = Instant.ofEpochMilli(Long.parseLong(t));
        Instant now = Instant.ofEpochMilli(System.currentTimeMillis());
        Duration duration = Duration.between(requestTimes, now);
        if (duration.toMinutes() > timeout) {
            return false;
        }
        return timestampCheck(t);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // log.info("postHandle");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // log.info("afterCompletion");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    /**
     * 时间戳校验 校验前端传过来的时间戳，前11位数字之和取个位数为校验数放在12位上，可以拦截90%的非法请求
     *
     * @param timestamp
     * @return
     */
    private boolean timestampCheck(String timestamp) {
        // 1726729500010
        // 1726729500050   5 == arr[7]

        if (!StringUtils.hasText(timestamp) || timestamp.length() != length) {
            return false;
        }
        var check = timestamp.charAt(position);
        var cr = timestamp.toCharArray();
        int result = 0;
        for (int i = 0; i < position; i++) {
            var c = (byte) cr[i];
            result += c;
        }
        result = result % 10;
        log.info("check:{}, result:{}", check, cr[result]);
        return (int) check == cr[result];
    }

    /**
     * 生成时间戳
     *
     * @return
     */
    private String timestamp() {
        return timestamp(System.currentTimeMillis());
    }

    /**
     * 生成时间戳
     *
     * @return
     */
    private String timestamp(Long timestamp) {
        System.out.println(timestamp);
        var arr = timestamp.toString().toCharArray();
        int r = 0;
        for (int i = 0; i < position; i++) {
            var c = (byte) arr[i];
            r += c;
        }
        r = r % 10;
        arr[position] = arr[r];
        return new String(arr);
    }

}
